﻿using System;
using System.Collections.Generic;
using ComputerBeacon.Csv;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UnitTestProject1 {
    [TestClass]
    public class ScannerTest {
        void AssertTokens(Scanner.Token[] expectedResult, List<Scanner.Token> actualResult) {
            Assert.AreEqual(expectedResult.Length, actualResult.Count);
            for (int i = 0; i < expectedResult.Length; i++) Assert.AreEqual(expectedResult[i], actualResult[i]);
        }

        [TestMethod]
        public void Oneline() {
            var s = new Scanner("1997,Ford,E350");
            var tokens = new List<Scanner.Token>();

            do { tokens.Add(s.Next()); }
            while(tokens[tokens.Count - 1].NextType != Scanner.TokenType.End);

            var answer = new Scanner.Token[] {
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "1997"},
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "Ford"},
                new Scanner.Token{ NextType = Scanner.TokenType.End, Value = "E350"}
            };

            AssertTokens(answer, tokens);
        }

        [TestMethod]
        public void TrailingComma() {
            var s = new Scanner("1997,Ford,E350,");
            var tokens = new List<Scanner.Token>();

            do { tokens.Add(s.Next()); }
            while (tokens[tokens.Count - 1].NextType != Scanner.TokenType.End);

            var answer = new Scanner.Token[] {
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "1997"},
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "Ford"},
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "E350"},
                new Scanner.Token{ NextType = Scanner.TokenType.End, Value = ""}
            };

            AssertTokens(answer, tokens);
        }

        [TestMethod]
        public void Newline() {
            var s = new Scanner("1997,Ford,E350,\n3,4,5,,6");
            var tokens = new List<Scanner.Token>();

            do { tokens.Add(s.Next()); }
            while (tokens[tokens.Count - 1].NextType != Scanner.TokenType.End);

            var answer = new Scanner.Token[] {
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "1997"},
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "Ford"},
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "E350"},
                new Scanner.Token{ NextType = Scanner.TokenType.Newline, Value = ""},
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "3"},
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "4"},
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "5"},
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = ""},
                new Scanner.Token{ NextType = Scanner.TokenType.End, Value = "6"},
            };

            AssertTokens(answer, tokens);
        }

        [TestMethod]
        public void SimpleQuote() {
            var s = new Scanner("\"1997\",\"Ford\",\"E350\"");
            var tokens = new List<Scanner.Token>();

            do { tokens.Add(s.Next()); }
            while (tokens[tokens.Count - 1].NextType != Scanner.TokenType.End);

            var answer = new Scanner.Token[] {
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "1997"},
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "Ford"},
                new Scanner.Token{ NextType = Scanner.TokenType.End, Value = "E350"}
            };

            AssertTokens(answer, tokens);
        }

        [TestMethod]
        public void CommaInQuotes() {
            var s = new Scanner("1997,Ford,E350,\"Super, luxurious truck\"");
            var tokens = new List<Scanner.Token>();

            do { tokens.Add(s.Next()); }
            while (tokens[tokens.Count - 1].NextType != Scanner.TokenType.End);

            var answer = new Scanner.Token[] {
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "1997"},
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "Ford"},
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "E350"},
                new Scanner.Token{ NextType = Scanner.TokenType.End, Value = "Super, luxurious truck"},
                
            };

            AssertTokens(answer, tokens);
        }

        [TestMethod]
        public void QuoteInQuotes() {
            var s = new Scanner("1997,Ford,E350,\"Super, \"\"luxurious\"\" truck\"");
            var tokens = new List<Scanner.Token>();

            do { tokens.Add(s.Next()); }
            while (tokens[tokens.Count - 1].NextType != Scanner.TokenType.End);

            var answer = new Scanner.Token[] {
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "1997"},
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "Ford"},
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "E350"},
                new Scanner.Token{ NextType = Scanner.TokenType.End, Value = "Super, \"luxurious\" truck"},
                
            };

            AssertTokens(answer, tokens);
        }

        [TestMethod]
        public void NewlineInQuotes() {
            var s = new Scanner("1997,Ford,E350,\"Go get one now\r\nthey are going fast\"");
            var tokens = new List<Scanner.Token>();

            do { tokens.Add(s.Next()); }
            while (tokens[tokens.Count - 1].NextType != Scanner.TokenType.End);

            var answer = new Scanner.Token[] {
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "1997"},
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "Ford"},
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "E350"},
                new Scanner.Token{ NextType = Scanner.TokenType.End, Value = "Go get one now\r\nthey are going fast"},
                
            };

            AssertTokens(answer, tokens);
        }

        [TestMethod]
        [ExpectedException(typeof(FormatException))]
        public void TerminatingQuoteMissing() {
            var s = new Scanner("1997,Ford,E350,\"Go get one now\r\nthey are going fast");
            var tokens = new List<Scanner.Token>();

            do { tokens.Add(s.Next()); }
            while (tokens[tokens.Count - 1].NextType != Scanner.TokenType.End);
        }

        [TestMethod]
        public void SpaceAndNewlineInData() {
            var s = new Scanner("1997, Ford, E350\r\nnot same as\r\n1997,Ford,E350");
            var tokens = new List<Scanner.Token>();

            do { tokens.Add(s.Next()); }
            while (tokens[tokens.Count - 1].NextType != Scanner.TokenType.End);

            var answer = new Scanner.Token[] {
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "1997"},
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = " Ford"},
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = " E350"},
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "not ssame as"},
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "1997"},
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "Ford"},
                new Scanner.Token{ NextType = Scanner.TokenType.End, Value = "E350"},
            };
        }

        [TestMethod]
        public void NoTrimSpace() {
            var s = new Scanner("1997,Ford,E350,\" Super luxurious truck \"");
            var tokens = new List<Scanner.Token>();

            do { tokens.Add(s.Next()); }
            while (tokens[tokens.Count - 1].NextType != Scanner.TokenType.End);

            var answer = new Scanner.Token[] {
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "1997"},
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "Ford"},
                new Scanner.Token{ NextType = Scanner.TokenType.String, Value = "E350"},
                new Scanner.Token{ NextType = Scanner.TokenType.End, Value = " Super luxurious truck "},
                
            };

            AssertTokens(answer, tokens);
        }
    }
}
